using System;
using System.Diagnostics;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.Timers;
using Utility.Win32_API;
using System.Threading;

namespace AAClicker
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class MainForm : System.Windows.Forms.Form
    {
        private System.Timers.Timer submissionTimer;
        private System.Timers.Timer okLookTimer;
        private int submissionCheckCount = 0;
        private LinkLabel linkAAClickerHelpLink;
        private Button btnHealthy;
        private Label lblMessage;
        private IContainer components;
        private GroupBox groupBox1;
        private Label label2;
        private Label label1;
        private NumericUpDown numericUpDownSubmissionInterval;
        private CheckBox chkWaitIdle;
        private Button btnCloseCalc;
        private Button btnGetWindows;
        private Label label3;
        private ProgressBar pbar;
        private System.Windows.Forms.Timer pbarTimer;
        public bool AutoSubmission;

        public MainForm()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            AutoSubmission = false;
            this.btnCloseCalc.Enabled = false;

            // Add a link to the LinkLabel.
            LinkLabel.Link link = new LinkLabel.Link();
            link.LinkData = "http://live.meetscoresonline.com/aaclickhelp.html";
            this.linkAAClickerHelpLink.Links.Add(link);


            //
            // TODO: Add any constructor code after InitializeComponent call
            //
            // Declare the Submission Timer
            submissionTimer = new System.Timers.Timer();
            //GC.KeepAlive(submissionTimer);
            submissionTimer.Interval = ((double)numericUpDownSubmissionInterval.Value) * 1000;
            // Hook up the submissionTimerElapsedHandler
            submissionTimer.Elapsed += new ElapsedEventHandler(OnSubmissionTimerElapsed);
            submissionTimer.SynchronizingObject = this;

            // todo examine what this does
            //submissionTimer.Elapsed += new ElapsedEventHandler(submissionTimer_Elapsed);

            // Declare the OK Look Timer
            okLookTimer = new System.Timers.Timer();
            //GC.KeepAlive(okLookTimer);

            // Hook up the submissionTimerElapsedHandler
            okLookTimer.Elapsed += new ElapsedEventHandler(OnOKLookTimerElapsed);
            okLookTimer.SynchronizingObject = this;

            // Set the Interval to 1 second
            okLookTimer.Interval = 1000;
        }

        void submissionTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            ShowMessage("Auto-Submission expired.  Please restart auto submission");
            AutoSubmission = false;
            ToggleButtonState(btnHealthy, true);
            ToggleButtonState(btnGetWindows, true);
            ToggleButtonState(btnCloseCalc, false);
        }

        delegate void callButtonState(Button ButtonControl, bool EnabledState);
        void ToggleButtonState(Button ButtonControl, bool EnabledState)
        {
            if (ButtonControl.InvokeRequired)
            {
                callButtonState d = new callButtonState(ToggleButtonState);
                this.Invoke(d, new Object[] { ButtonControl, EnabledState });
            }
            else
                ButtonControl.Enabled = EnabledState;

        }
        delegate void togglePBarState(Color Color);
        // color: blue running, green sending, orange paused, red error
        public void TogglePBarState(Color Color)
        {
            if (pbar.InvokeRequired)
            {
                var d = new togglePBarState(TogglePBarState);
                this.Invoke(d, new Object[] { Color });
            }
            else
            {
                pbar.ForeColor = Color;
                Application.DoEvents();
            }
        }


        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
            this.linkAAClickerHelpLink = new System.Windows.Forms.LinkLabel();
            this.btnHealthy = new System.Windows.Forms.Button();
            this.lblMessage = new System.Windows.Forms.Label();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.label2 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.numericUpDownSubmissionInterval = new System.Windows.Forms.NumericUpDown();
            this.chkWaitIdle = new System.Windows.Forms.CheckBox();
            this.btnCloseCalc = new System.Windows.Forms.Button();
            this.btnGetWindows = new System.Windows.Forms.Button();
            this.label3 = new System.Windows.Forms.Label();
            this.pbar = new System.Windows.Forms.ProgressBar();
            this.pbarTimer = new System.Windows.Forms.Timer(this.components);
            this.groupBox1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownSubmissionInterval)).BeginInit();
            this.SuspendLayout();
            // 
            // linkAAClickerHelpLink
            // 
            this.linkAAClickerHelpLink.AutoSize = true;
            this.linkAAClickerHelpLink.ForeColor = System.Drawing.Color.Blue;
            this.linkAAClickerHelpLink.Location = new System.Drawing.Point(267, 82);
            this.linkAAClickerHelpLink.Name = "linkAAClickerHelpLink";
            this.linkAAClickerHelpLink.Size = new System.Drawing.Size(111, 13);
            this.linkAAClickerHelpLink.TabIndex = 6;
            this.linkAAClickerHelpLink.TabStop = true;
            this.linkAAClickerHelpLink.Text = "Help Using AA Clicker";
            this.linkAAClickerHelpLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkAAClickerHelpLink_LinkClicked);
            this.linkAAClickerHelpLink.Click += new System.EventHandler(this.linkAAClickerHelpLink_Clicked);
            // 
            // btnHealthy
            // 
            this.btnHealthy.Location = new System.Drawing.Point(258, 98);
            this.btnHealthy.Name = "btnHealthy";
            this.btnHealthy.Size = new System.Drawing.Size(136, 23);
            this.btnHealthy.TabIndex = 7;
            this.btnHealthy.Text = "Healthy?";
            this.btnHealthy.UseVisualStyleBackColor = true;
            this.btnHealthy.Click += new System.EventHandler(this.btnHealthy_Click);
            // 
            // lblMessage
            // 
            this.lblMessage.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.lblMessage.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.lblMessage.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.lblMessage.Location = new System.Drawing.Point(13, 152);
            this.lblMessage.Name = "lblMessage";
            this.lblMessage.Size = new System.Drawing.Size(376, 158);
            this.lblMessage.TabIndex = 8;
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.label2);
            this.groupBox1.Controls.Add(this.label1);
            this.groupBox1.Controls.Add(this.numericUpDownSubmissionInterval);
            this.groupBox1.Controls.Add(this.chkWaitIdle);
            this.groupBox1.Controls.Add(this.btnCloseCalc);
            this.groupBox1.Controls.Add(this.btnGetWindows);
            this.groupBox1.Location = new System.Drawing.Point(13, 6);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(229, 114);
            this.groupBox1.TabIndex = 10;
            this.groupBox1.TabStop = false;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(176, 45);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(47, 13);
            this.label2.TabIndex = 15;
            this.label2.Text = "seconds";
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(13, 45);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(103, 13);
            this.label1.TabIndex = 14;
            this.label1.Text = "Submit Queue every";
            // 
            // numericUpDownSubmissionInterval
            // 
            this.numericUpDownSubmissionInterval.Location = new System.Drawing.Point(122, 43);
            this.numericUpDownSubmissionInterval.Maximum = new decimal(new int[] {
            300,
            0,
            0,
            0});
            this.numericUpDownSubmissionInterval.Minimum = new decimal(new int[] {
            10,
            0,
            0,
            0});
            this.numericUpDownSubmissionInterval.Name = "numericUpDownSubmissionInterval";
            this.numericUpDownSubmissionInterval.Size = new System.Drawing.Size(48, 20);
            this.numericUpDownSubmissionInterval.TabIndex = 13;
            this.numericUpDownSubmissionInterval.Value = new decimal(new int[] {
            10,
            0,
            0,
            0});
            // 
            // chkWaitIdle
            // 
            this.chkWaitIdle.AutoSize = true;
            this.chkWaitIdle.Checked = true;
            this.chkWaitIdle.CheckState = System.Windows.Forms.CheckState.Checked;
            this.chkWaitIdle.Location = new System.Drawing.Point(155, 13);
            this.chkWaitIdle.Name = "chkWaitIdle";
            this.chkWaitIdle.Size = new System.Drawing.Size(68, 17);
            this.chkWaitIdle.TabIndex = 12;
            this.chkWaitIdle.Text = "Wait Idle";
            this.chkWaitIdle.UseVisualStyleBackColor = true;
            // 
            // btnCloseCalc
            // 
            this.btnCloseCalc.Location = new System.Drawing.Point(9, 76);
            this.btnCloseCalc.Name = "btnCloseCalc";
            this.btnCloseCalc.Size = new System.Drawing.Size(214, 23);
            this.btnCloseCalc.TabIndex = 11;
            this.btnCloseCalc.Text = "Stop";
            // 
            // btnGetWindows
            // 
            this.btnGetWindows.Location = new System.Drawing.Point(6, 9);
            this.btnGetWindows.Name = "btnGetWindows";
            this.btnGetWindows.Size = new System.Drawing.Size(143, 23);
            this.btnGetWindows.TabIndex = 10;
            this.btnGetWindows.Text = "Start";
            this.btnGetWindows.Click += new System.EventHandler(this.btnGetWindows_Click);
            // 
            // label3
            // 
            this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.label3.Location = new System.Drawing.Point(258, 13);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(136, 69);
            this.label3.TabIndex = 11;
            this.label3.Text = "AAClicker by MeetScoresOnline automates and optimizes publishing your scores ";
            // 
            // pbar
            // 
            this.pbar.ForeColor = System.Drawing.Color.DodgerBlue;
            this.pbar.Location = new System.Drawing.Point(12, 126);
            this.pbar.Name = "pbar";
            this.pbar.Size = new System.Drawing.Size(382, 13);
            this.pbar.TabIndex = 12;
            // 
            // pbarTimer
            // 
            this.pbarTimer.Interval = 1000;
            this.pbarTimer.Tick += new System.EventHandler(this.pbarTimer_Tick);
            // 
            // MainForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(400, 146);
            this.Controls.Add(this.pbar);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.lblMessage);
            this.Controls.Add(this.btnHealthy);
            this.Controls.Add(this.linkAAClickerHelpLink);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.MaximizeBox = false;
            this.Name = "MainForm";
            this.Text = "AA Clicker";
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDownSubmissionInterval)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        void pbarTimer_Tick(object sender, EventArgs e)
        {
            pbar.PerformStep();
        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new MainForm());
        }

        // Handle the submissionTimer Elapsed method
        private void OnSubmissionTimerElapsed(object source, ElapsedEventArgs e)
        {
            int hwndPublish = 0;
            IntPtr hwndChild = IntPtr.Zero;

            // Stop the Submission Timer since we don't know how long it will take 
            // for the Publish Successfull message to show up.
            (source as System.Timers.Timer).Enabled = false;

            //Get a handle for the Public to MeetScoresOnline.com window
            hwndPublish = Win32.FindWindow(null, "Publish to MeetScoresOnline.com");

            pbarTimer.Stop();
            if (hwndPublish == 0)
            {
                TogglePBarState(Color.Red);
                ShowMessage("Couldn't find the Publish to MeetScoresOnline.com window.");
                return;
            }


            //Get a handle for the "Publish Results Queue" button
            hwndChild = Win32.FindWindowEx((IntPtr)hwndPublish, IntPtr.Zero, "TcxButton", "Publish Results Queue");

            // wait for healthy internet
            try
            {

                //MainForm.ThisForm.ShowMessage("Sending...");

                // wait for idle user
                TogglePBarState(Color.Orange);
                while (!Win32.UserIdle(8)) { }

                // wait for healthy internet
                while (!Utility.Internet.InternetUtility.TestHealthyWebService()) { }

                // wait for idle user
                while (!Win32.UserIdle(8)) { }

                // if the user has clicked the stop button during their un-idle time
                if (!AutoSubmission)
                {
                    TogglePBarState(Color.Gray);
                    return;
                }
                //send BN_CLICKED message


                TogglePBarState(Color.Green);
                Win32.SendNotifyMessage(hwndChild, Win32.BN_CLICKED, UIntPtr.Zero, IntPtr.Zero);
                okLookTimer.Enabled = true;
            }
            catch (AAExceptionServiceUnreachable)
            {

                okLookTimer.Enabled = false;
            }
            catch (Exception unhandled)
            {
                okLookTimer.Enabled = false;
            }
        }

        // Start
        private void btnGetWindows_Click(object sender, System.EventArgs e)
        {
            HideMessage();

            // Disable the Start button so it can only be clicked once.
            this.btnGetWindows.Enabled = false;

            // Disable the Submission Interval Numeric Control so it can't be changed.
            this.numericUpDownSubmissionInterval.Enabled = false;

            // Enable the Stop button so the timers can be stopped.
            this.btnCloseCalc.Enabled = true;
            submissionTimer.Enabled = true;
            AutoSubmission = true;

            pbar.Enabled = true;
            pbar.Maximum = Convert.ToInt32(numericUpDownSubmissionInterval.Value);
            pbar.Minimum = 0;
            pbar.Step = 1;
            pbar.Value = 0;
            pbarTimer.Start();
            Application.DoEvents();
            /*
            hwndChild = (IntPtr)0x0003079E;
            // Send Publish Message
            SendMessage((int)hwndChild, BN_CLICKED, 0, IntPtr.Zero);
             */
        }

        // Handle the onOKLookTimer Elapsed method
        private void OnOKLookTimerElapsed(object source, ElapsedEventArgs e)
        {

            int hwndPublish = 0;
            int hwndPublishError = 0;
            int hwndPublishSuccess = 0;
            IntPtr hwndChild = IntPtr.Zero;

            // Stop the OK Look Timer since it will be restared by the Submission Timer
            (source as System.Timers.Timer).Enabled = false;

            hwndPublish = Win32.FindWindow(null, "Publish to MeetScoresOnline.com");
            if (hwndPublish == 0)
            {
                ShowMessage("Couldn't find the Publish to MeetScoresOnline.com window.");
                return;
            }

            //Get a handle for the Error Publishing to MeetScoresOnline.com window
            hwndPublishError = Win32.FindWindow(null, "Error Publishing to MeetScoresOnline.com");

            // Set the submissionCheckCount > 300 if the Error Publishing... dialog is found
            if (hwndPublishError != 0)
            {
                submissionCheckCount = 301;
            }

            if (submissionCheckCount > 300)
            {
                submissionTimer.Enabled = false;
                ShowMessage("The publish was not successful. Please close AA Clicker and try again later.");
                return;
            }

            if (hwndPublishError != 0)
            {
                submissionTimer.Enabled = false;
                ShowMessage("The publish was not successful. Please close AA Clicker and try again later.");
            }

            //Get a handle for the Successful Publish to MeetScoresOnline.com window
            hwndPublishSuccess = Win32.FindWindow(null, "Successful Publish to MeetScoresOnline.com");

            if (hwndPublishSuccess == 0)
            {
                submissionCheckCount++;
                // Start the OK Look Timer so it will try again.
                (source as System.Timers.Timer).Enabled = true;
            }
            else
            {
                submissionCheckCount = 0;

                Worker wrkr = new Worker();
                var w = new Worker.workerPointerDelegate(wrkr.Work);
                w.Invoke((IntPtr)hwndPublishSuccess);
                submissionTimer.Enabled = true;
                pbar.Value = 0;
                pbarTimer.Enabled = true;
                TogglePBarState(Color.Blue);
            }
        }



        // Stop button
        private void btnCloseCalc_Click(object sender, System.EventArgs e)
        {
            // Stop all timers.
            submissionTimer.Enabled = false;
            okLookTimer.Enabled = false;

            // Enable the Start button so the timers can be started
            btnGetWindows.Enabled = true;

            // Enable the Submission Interval Numeric Control so it can be changed.
            this.numericUpDownSubmissionInterval.Enabled = true;

            // Disable the Stop button since the timers have stopped.
            btnCloseCalc.Enabled = false;

            AutoSubmission = false;
        }

        private void numericUpDownSubmissionInterval_ValueChanged(object sender, EventArgs e)
        {
            var interval = (sender as System.Windows.Forms.NumericUpDown).Value * 1000;
            submissionTimer.Interval = (double)interval;
        }

        private void linkAAClickerHelpLink_Clicked(object sender, System.EventArgs e)
        {
            // Send the URL to the operating system.
            Process.Start((sender as System.Windows.Forms.LinkLabel).Links[0].LinkData as string);
        }

        private void linkAAClickerHelpLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            // Send the URL to the operating system.
            Process.Start(e.Link.LinkData as string);
        }

        private void btnHealthy_Click(object sender, EventArgs e)
        {
            try
            {
                RegistryTools.OptimizeWebPublishing();

                btnHealthy.Text = "Testing..";
                btnHealthy.Enabled = false;
                Application.DoEvents();
                Utility.Internet.InternetUtility.Reset();
                while (!Utility.Internet.InternetUtility.TestHealthyWebService()) { }
                HideMessage();
                btnHealthy.Enabled = true;
                btnHealthy.Text = "Healthy!";
                btnHealthy.ForeColor = Color.Green;
            }
            catch (AAExceptionServiceUnreachable)
            {
                ShowMessage("Exception Caught - See Details below.  Contact MSO if this problem persists.");

                foreach (UnreachableArgs args in AAExceptionServiceUnreachable.ListExceptions())
                    AppendMessage(args.Serialize());

                btnHealthy.Enabled = true;
                btnHealthy.Text = "Not Healthy";
                btnHealthy.ForeColor = Color.Red;
            }
            catch (Exception unhandled)
            {
                ShowMessage("Unhandled Exception Caught -  See Exception below");

                var ex = unhandled;
                while (ex != null)
                {
                    AppendMessage(ex.Message);
                    ex = ex.InnerException;
                }
            }



        }

        public void HideMessage()
        {
            this.Height = 174;
        }
        delegate void SetTextCallback(string text);
        public void ShowMessage(String Message)
        {
            if (this.lblMessage.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(ShowMessage);
                this.Invoke(d, new Object[] { Message });
            }
            else
            {
                this.lblMessage.Text = Message + "\n\n";
                this.lblMessage.ForeColor = Color.Red;
                this.Height = 325;
            }
        }
        public void AppendMessage(String Message)
        {
            lblMessage.Text += "\n" + Message;
        }

    }


    public class Worker
    {
        public delegate void workerPointerDelegate(IntPtr Obj);

        public void Work(IntPtr Obj)
        {
            //Get a handle for the "Publish Results Queue" button
            var hwndChild = Win32.FindWindowEx(Obj, IntPtr.Zero, "Button", "OK");

            //send BN_CLICKED message
            Win32.SendMessage((int)hwndChild, Win32.BN_CLICKED, 0, IntPtr.Zero);


        }

    }

}
